package com.apkcore.core.util

import android.os.Handler
import android.os.Looper
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner

object TimeoutUtil {
    private val handler by lazy { Handler(Looper.getMainLooper()) }
    private val actions by lazy { mutableMapOf<String, Runnable>() }

    /**
     * 开启定时
     */
    @JvmOverloads
    fun start(
        taskName: String? = null,
        delayMillis: Long,
        periodMillis: Long = -1,
        lifecycleOwner:LifecycleOwner? = null,
//        taskType: Int = TaskType.ONCE,
        clz: Class<out Any>? = null,
        task: () -> Unit
    ) {
        if (taskName == null && clz == null) {
            throw Throwable(message = "taskName和clz不能同时为空")
        }
        val actualTaskName = taskName ?: getCallerMethodName(clz!!)
        stop(actualTaskName)
        val runnable = object : Runnable {
            override fun run() {
                try {
                    task()
                }catch (e:Throwable){}
                if (periodMillis >= 0) {
                    handler.postDelayed(this, periodMillis)
                }
            }
        }
        actions[actualTaskName] = runnable
        if (periodMillis >= 0) {
//        if (taskType == TaskType.REPEATED && periodMillis >= 0) {
            handler.postDelayed(runnable, delayMillis)
        } else {
            handler.postDelayed(runnable, delayMillis)
        }
        lifecycleOwner?.lifecycle?.addObserver(object :DefaultLifecycleObserver{
            override fun onStop(owner: LifecycleOwner) {
                stop(actualTaskName)
                super.onStop(owner)
            }
        })
    }

    /**
     * 关闭定时器
     */
    fun stop(taskName: String, runNow: Boolean = false) {
        actions[taskName]?.let {
            if (runNow) {
                handler.post(it)
            } else {
                handler.removeCallbacks(it)
            }
            actions.remove(taskName)
        }
    }

    /**
     * 清除所有定时任务
     */
    fun stopAll() {
        actions.values.forEach {
            handler.removeCallbacks(it)
        }
        handler.removeCallbacksAndMessages(null)
        actions.clear()
    }

    private fun getCallerMethodName(clz: Class<out Any>): String {
        val stackTrace = Thread.currentThread().stackTrace
        var callerMethodName = ""
        for (i in 2 until stackTrace.size) {
            val declaringClass = stackTrace[i].className
            if (declaringClass == clz.name) {
                val methodName = stackTrace[i].methodName
                callerMethodName = methodName
                break
            }
        }
        return callerMethodName
    }
}

//object TaskType {
//    const val ONCE = 0
//    const val REPEATED = 1
//}
